package com.ruoyi.web.controller.tool;

import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import groovy.lang.Script;
import lombok.extern.slf4j.Slf4j;
import org.apache.groovy.parser.antlr4.util.StringUtils;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: lly
 * @Date: 2023/7/1
 */
@Slf4j
@Service
public class GroovyClassLoaderRuleImpl implements GroovyClassLoaderRule {

    /**
     * 脚本容器 ：缓存Script，避免创建太多
     **/
    private static final Map<String, GroovyObject> SCRIPT_MAP = new HashMap<>();

    private static final GroovyClassLoader CLASS_LOADER = new GroovyClassLoader();

    public static GroovyObject loadScript(String key, String rule) {
        if (SCRIPT_MAP.containsKey(key)) {
            return SCRIPT_MAP.get(key);
        }
        GroovyObject groovyObject = loadScript(rule);
        SCRIPT_MAP.put(key, groovyObject);
        return groovyObject;
    }

    public static GroovyObject loadScript(String rule) {
        if (StringUtils.isEmpty(rule)) {
            return null;
        }
        try {
            Class ruleClazz = CLASS_LOADER.parseClass(rule);
            if (ruleClazz != null) {
                log.info("load rule:" + rule + " success!");
                GroovyObject groovyObject = (GroovyObject) ruleClazz.newInstance();
                return groovyObject;
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            CLASS_LOADER.clearCache();
        }

        log.error("load rule error, can not load Script");
        return null;
    }


    @Override
    public String run() {
        // 业务逻辑执行，方便配置
        String groovyClassLoader1 = "package script\n" +
                "\n" +
                "import com.example.groovy.GroovyInvokeJavaDemo\n" +
                "import com.example.groovy.groovyshell.ShellGroovyDTO\n" +
                "import com.example.groovy.utils.SpringContextUtil\n" +
                "\n" +
                "/**\n" +
                " * @Author: lly\n" +
                " * @Date: 2023/7/1\n" +
                " */\n" +
                "\n" +
                "def groovyInvokeJavaMethod(int a, int b) {\n" +
                "    GroovyInvokeJavaDemo groovyInvokeJavaDemo = SpringContextUtil.getBean(\"groovyInvokeJavaDemo\")\n" +
                "//    return groovyInvokeJavaDemo.groovyInvokeJava();\n" +
                "\n" +
                "    return groovyInvokeJavaDemo.groovyInvokeJavaParam(a, b)\n" +
                "}\n" +
                "\n" +
                "groovyInvokeJavaMethod(a, b)";

        String groovyClassLoader2 = "package script\n" +
                "\n" +
                "import com.example.groovy.GroovyInvokeJavaDemo\n" +
                "import com.example.groovy.groovyshell.ShellGroovyDTO\n" +
                "import com.example.groovy.utils.SpringContextUtil\n" +
                "\n" +
                "/**\n" +
                " * @Author: lly\n" +
                " * @Date: 2023/7/1\n" +
                " */\n" +
                "\n" +
                "def groovyInvokeJavaMethod(int a, int b) {\n" +
                "    GroovyInvokeJavaDemo groovyInvokeJavaDemo = SpringContextUtil.getBean(\"groovyInvokeJavaDemo\")\n" +
                "//    return groovyInvokeJavaDemo.groovyInvokeJava();\n" +
                "\n" +
                "    return groovyInvokeJavaDemo.groovyInvokeJavaParam(a, b)\n" +
                "}\n" +
                "\n" +
                "groovyInvokeJavaMethod(a, b)";

        Binding binding = new Binding();
        binding.setVariable("a", 300);
        binding.setVariable("b", 400);

//        Script classLoader1 = loadScript("groovyClassLoader1", groovyClassLoader1, binding);
        GroovyObject groovyObject = loadScript("groovyClassLoader2", groovyClassLoader2);

        Object groovyInvokeJavaMethod = groovyObject.invokeMethod("groovyInvokeJavaMethod", new Object[]{100, 200});

        return (String) groovyInvokeJavaMethod;
    }
}

